package com.aspire.aimini.service.impl;

import com.aspire.aimini.repository.*;
import com.aspire.aimini.service.StatisticsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 统计分析服务实现类
 *
 * @author wangguiyou
 * @date 2024-12-19
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StatisticsServiceImpl implements StatisticsService {

    private final MaterialRepository materialRepository;
    private final TagRepository tagRepository;
    private final CopywritingRepository copywritingRepository;
    private final AiConfigRepository aiConfigRepository;
    private final GenerationRecordRepository generationRecordRepository;
    private final UserRepository userRepository;

    /**
     * 获取用户统计信息
     *
     * @param userId 用户ID
     * @return 用户统计信息
     */
    @Override
    public Map<String, Object> getUserStatistics(Long userId) {
        log.info("获取用户统计信息: userId={}", userId);

        Map<String, Object> statistics = new HashMap<>();

        // 素材统计
        statistics.put("materialCount", materialRepository.countByUserId(userId));
        statistics.put("materialViewCount", materialRepository.sumViewCountByUserId(userId));
        statistics.put("materialDownloadCount", materialRepository.sumDownloadCountByUserId(userId));

        // 文案统计
        statistics.put("copywritingCount", copywritingRepository.countByUserId(userId));
        statistics.put("copywritingUsageCount", copywritingRepository.sumUsageCountByUserId(userId));

        // AI使用统计
        statistics.put("aiGenerationCount", generationRecordRepository.countByUserId(userId));
        statistics.put("aiTotalCost", generationRecordRepository.sumCostByUserId(userId));

        // 今日统计
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        LocalDateTime todayEnd = todayStart.plusDays(1);
        statistics.put("todayMaterialCount",
                materialRepository.countByUserIdAndDateRange(userId, todayStart, todayEnd));
        statistics.put("todayCopywritingCount",
                copywritingRepository.countByUserIdAndDateRange(userId, todayStart, todayEnd));
        statistics.put("todayAiGenerationCount",
                generationRecordRepository.countByUserIdAndDateRange(userId, todayStart, todayEnd));

        return statistics;
    }

    /**
     * 获取系统统计信息
     *
     * @return 系统统计信息
     */
    @Override
    public Map<String, Object> getSystemStatistics() {
        log.info("获取系统统计信息");

        Map<String, Object> statistics = new HashMap<>();

        // 用户统计
        statistics.put("totalUsers", userRepository.countTotal());
        statistics.put("activeUsers", userRepository.countActiveUsers());

        // 素材统计
        statistics.put("totalMaterials", materialRepository.countTotal());
        statistics.put("totalMaterialViews", materialRepository.sumTotalViewCount());
        statistics.put("totalMaterialDownloads", materialRepository.sumTotalDownloadCount());

        // 标签统计
        statistics.put("totalTags", tagRepository.countTotal());
        statistics.put("systemTags", tagRepository.countSystemTags());
        statistics.put("customTags", tagRepository.countCustomTags());

        // 文案统计
        statistics.put("totalCopywritings", copywritingRepository.countTotal());
        statistics.put("totalCopywritingUsage", copywritingRepository.sumTotalUsageCount());

        // AI统计
        statistics.put("totalAiGenerations", generationRecordRepository.countTotal());
        statistics.put("totalAiCost", generationRecordRepository.sumTotalCost());
        statistics.put("aiSuccessRate", generationRecordRepository.calculateSuccessRate());

        return statistics;
    }

    /**
     * 获取热门标签统计
     *
     * @param limit 数量限制
     * @return 热门标签列表
     */
    @Override
    public List<Map<String, Object>> getPopularTagsStatistics(int limit) {
        log.info("获取热门标签统计: limit={}", limit);

        return tagRepository.getPopularTagsWithUsageCount(limit);
    }

    /**
     * 获取热门素材统计
     *
     * @param limit 数量限制
     * @return 热门素材列表
     */
    @Override
    public List<Map<String, Object>> getPopularMaterialsStatistics(int limit) {
        log.info("获取热门素材统计: limit={}", limit);

        return materialRepository.getPopularMaterialsWithStats(limit);
    }

    /**
     * 获取热门文案统计
     *
     * @param limit 数量限制
     * @return 热门文案列表
     */
    @Override
    public List<Map<String, Object>> getPopularCopywritingsStatistics(int limit) {
        log.info("获取热门文案统计: limit={}", limit);

        return copywritingRepository.getPopularCopywritingsWithStats(limit);
    }

    /**
     * 获取用户素材统计
     *
     * @param userId 用户ID
     * @return 素材统计信息
     */
    @Override
    public Map<String, Object> getUserMaterialStatistics(Long userId) {
        log.info("获取用户素材统计: userId={}", userId);

        Map<String, Object> statistics = new HashMap<>();

        statistics.put("totalCount", materialRepository.countByUserId(userId));
        statistics.put("totalSize", materialRepository.sumFileSizeByUserId(userId));
        statistics.put("totalViews", materialRepository.sumViewCountByUserId(userId));
        statistics.put("totalDownloads", materialRepository.sumDownloadCountByUserId(userId));
        statistics.put("favoriteCount", materialRepository.countFavoriteByUserId(userId));
        statistics.put("countByFileType", materialRepository.getCountByFileTypeAndUserId(userId));
        statistics.put("countBySourceType", materialRepository.getCountBySourceTypeAndUserId(userId));

        return statistics;
    }

    /**
     * 获取用户文案统计
     *
     * @param userId 用户ID
     * @return 文案统计信息
     */
    @Override
    public Map<String, Object> getUserCopywritingStatistics(Long userId) {
        log.info("获取用户文案统计: userId={}", userId);

        Map<String, Object> statistics = new HashMap<>();

        statistics.put("totalCount", copywritingRepository.countByUserId(userId));
        statistics.put("totalUsage", copywritingRepository.sumUsageCountByUserId(userId));
        statistics.put("favoriteCount", copywritingRepository.countFavoriteByUserId(userId));
        statistics.put("countByContentType", copywritingRepository.getCountByContentTypeAndUserId(userId));
        statistics.put("countByStyle", copywritingRepository.getCountByStyleAndUserId(userId));
        statistics.put("countByAiModel", copywritingRepository.getCountByAiModelAndUserId(userId));

        return statistics;
    }

    /**
     * 获取用户AI使用统计
     *
     * @param userId 用户ID
     * @return AI使用统计信息
     */
    @Override
    public Map<String, Object> getUserAiUsageStatistics(Long userId) {
        log.info("获取用户AI使用统计: userId={}", userId);

        Map<String, Object> statistics = new HashMap<>();

        statistics.put("totalGenerations", generationRecordRepository.countByUserId(userId));
        statistics.put("successfulGenerations", generationRecordRepository.countSuccessfulByUserId(userId));
        statistics.put("failedGenerations", generationRecordRepository.countFailedByUserId(userId));
        statistics.put("totalCost", generationRecordRepository.sumCostByUserId(userId));
        statistics.put("averageResponseTime", generationRecordRepository.getAverageResponseTimeByUserId(userId));
        statistics.put("countByGenerationType", generationRecordRepository.getCountByGenerationTypeAndUserId(userId));
        statistics.put("countByProvider", generationRecordRepository.getCountByProviderAndUserId(userId));
        statistics.put("countByModel", generationRecordRepository.getCountByModelAndUserId(userId));

        return statistics;
    }

    /**
     * 按类型统计素材数量
     *
     * @return 统计结果
     */
    @Override
    public Map<String, Long> getMaterialCountByType() {
        log.info("按类型统计素材数量");

        return materialRepository.getCountByFileType();
    }

    /**
     * 按类型统计文案数量
     *
     * @return 统计结果
     */
    @Override
    public Map<String, Long> getCopywritingCountByType() {
        log.info("按类型统计文案数量");

        return copywritingRepository.getCountByContentType();
    }

    /**
     * 按类型统计AI使用数量
     *
     * @return 统计结果
     */
    @Override
    public Map<String, Long> getAiUsageCountByType() {
        log.info("按类型统计AI使用数量");

        return generationRecordRepository.getCountByGenerationType();
    }

    /**
     * 获取每日上传统计
     *
     * @param days 天数
     * @return 每日上传统计
     */
    @Override
    public Map<String, Long> getDailyUploadStatistics(int days) {
        log.info("获取每日上传统计: days={}", days);

        return materialRepository.getDailyUploadCount(days);
    }

    /**
     * 获取每日生成统计
     *
     * @param days 天数
     * @return 每日生成统计
     */
    @Override
    public Map<String, Long> getDailyGenerationStatistics(int days) {
        log.info("获取每日生成统计: days={}", days);

        return copywritingRepository.getDailyGenerationCount(days);
    }

    /**
     * 获取每日AI使用统计
     *
     * @param days 天数
     * @return 每日AI使用统计
     */
    @Override
    public Map<String, Long> getDailyAiUsageStatistics(int days) {
        log.info("获取每日AI使用统计: days={}", days);

        return generationRecordRepository.getDailyGenerationCount(days);
    }

    /**
     * 获取每日消耗统计
     *
     * @param days 天数
     * @return 每日消耗统计
     */
    @Override
    public Map<String, BigDecimal> getDailyCostStatistics(int days) {
        log.info("获取每日消耗统计: days={}", days);

        return generationRecordRepository.getDailyCostAmount(days);
    }

    /**
     * 获取用户活跃度统计
     *
     * @param days 天数
     * @return 用户活跃度统计
     */
    @Override
    public Map<String, Object> getUserActivityStatistics(int days) {
        log.info("获取用户活跃度统计: days={}", days);

        Map<String, Object> statistics = new HashMap<>();

        LocalDateTime startDate = LocalDateTime.now().minusDays(days);

        statistics.put("activeUsers", userRepository.countActiveUsersSince(startDate));
        statistics.put("newUsers", userRepository.countNewUsersSince(startDate));
        statistics.put("dailyActiveUsers", userRepository.getDailyActiveUsersCount(days));
        statistics.put("userRetentionRate", calculateUserRetentionRate(days));

        return statistics;
    }

    /**
     * 获取存储使用统计
     *
     * @return 存储使用统计
     */
    @Override
    public Map<String, Object> getStorageUsageStatistics() {
        log.info("获取存储使用统计");

        Map<String, Object> statistics = new HashMap<>();

        statistics.put("totalStorageUsed", materialRepository.sumTotalFileSize());
        statistics.put("storageByFileType", materialRepository.getStorageByFileType());
        statistics.put("storageByUser", materialRepository.getStorageByUser());
        statistics.put("averageFileSize", materialRepository.getAverageFileSize());

        return statistics;
    }

    /**
     * 获取系统性能统计
     *
     * @return 系统性能统计
     */
    @Override
    public Map<String, Object> getSystemPerformanceStatistics() {
        log.info("获取系统性能统计");

        Map<String, Object> statistics = new HashMap<>();

        // AI服务性能统计
        statistics.put("averageAiResponseTime", generationRecordRepository.getAverageResponseTime());
        statistics.put("aiSuccessRate", generationRecordRepository.calculateSuccessRate());
        statistics.put("aiErrorRate", generationRecordRepository.calculateErrorRate());

        // 系统负载统计
        statistics.put("totalRequests", getTotalRequestsCount());
        statistics.put("errorRequests", getErrorRequestsCount());
        statistics.put("systemUptime", getSystemUptime());

        return statistics;
    }

    /**
     * 获取用户排行榜
     *
     * @param type  排行类型
     * @param limit 数量限制
     * @return 用户排行榜
     */
    @Override
    public List<Map<String, Object>> getUserRanking(String type, int limit) {
        log.info("获取用户排行榜: type={}, limit={}", type, limit);

        switch (type.toLowerCase()) {
            case "material_count":
                return materialRepository.getUserRankingByMaterialCount(limit);
            case "material_views":
                return materialRepository.getUserRankingByViewCount(limit);
            case "copywriting_count":
                return copywritingRepository.getUserRankingByCopywritingCount(limit);
            case "ai_usage":
                return generationRecordRepository.getUserRankingByAiUsage(limit);
            default:
                return Collections.emptyList();
        }
    }

    /**
     * 获取AI服务使用统计
     *
     * @return AI服务使用统计
     */
    @Override
    public Map<String, Object> getAiServiceUsageStatistics() {
        log.info("获取AI服务使用统计");

        Map<String, Object> statistics = new HashMap<>();

        statistics.put("totalGenerations", generationRecordRepository.countTotal());
        statistics.put("successfulGenerations", generationRecordRepository.countSuccessful());
        statistics.put("failedGenerations", generationRecordRepository.countFailed());
        statistics.put("totalCost", generationRecordRepository.sumTotalCost());
        statistics.put("averageResponseTime", generationRecordRepository.getAverageResponseTime());
        statistics.put("countByProvider", generationRecordRepository.getCountByProvider());
        statistics.put("countByModel", generationRecordRepository.getCountByModel());
        statistics.put("countByGenerationType", generationRecordRepository.getCountByGenerationType());

        return statistics;
    }

    /**
     * 获取错误统计
     *
     * @param days 天数
     * @return 错误统计
     */
    @Override
    public Map<String, Object> getErrorStatistics(int days) {
        log.info("获取错误统计: days={}", days);

        Map<String, Object> statistics = new HashMap<>();

        LocalDateTime startDate = LocalDateTime.now().minusDays(days);

        statistics.put("totalErrors", generationRecordRepository.countFailedSince(startDate));
        statistics.put("errorsByType", generationRecordRepository.getErrorCountByType(startDate));
        statistics.put("errorsByProvider", generationRecordRepository.getErrorCountByProvider(startDate));
        statistics.put("dailyErrors", generationRecordRepository.getDailyErrorCount(days));

        return statistics;
    }

    /**
     * 获取用户增长统计
     *
     * @param days 天数
     * @return 用户增长统计
     */
    @Override
    public Map<String, Object> getUserGrowthStatistics(int days) {
        log.info("获取用户增长统计: days={}", days);

        Map<String, Object> statistics = new HashMap<>();

        statistics.put("totalUsers", userRepository.countTotal());
        statistics.put("newUsers", userRepository.countNewUsersSince(LocalDateTime.now().minusDays(days)));
        statistics.put("dailyNewUsers", userRepository.getDailyNewUsersCount(days));
        statistics.put("userGrowthRate", calculateUserGrowthRate(days));

        return statistics;
    }

    /**
     * 获取收入统计
     *
     * @param days 天数
     * @return 收入统计
     */
    @Override
    public Map<String, Object> getRevenueStatistics(int days) {
        log.info("获取收入统计: days={}", days);

        Map<String, Object> statistics = new HashMap<>();

        LocalDateTime startDate = LocalDateTime.now().minusDays(days);

        statistics.put("totalRevenue", generationRecordRepository.sumCostSince(startDate));
        statistics.put("dailyRevenue", generationRecordRepository.getDailyCostAmount(days));
        statistics.put("revenueByProvider", generationRecordRepository.getCostByProvider(startDate));
        statistics.put("revenueByServiceType", generationRecordRepository.getCostByServiceType(startDate));

        return statistics;
    }

    /**
     * 生成统计报告
     *
     * @param type      报告类型
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @return 统计报告
     */
    @Override
    public Map<String, Object> generateStatisticsReport(String type, LocalDateTime startDate, LocalDateTime endDate) {
        log.info("生成统计报告: type={}, startDate={}, endDate={}", type, startDate, endDate);

        Map<String, Object> report = new HashMap<>();
        report.put("reportType", type);
        report.put("startDate", startDate);
        report.put("endDate", endDate);
        report.put("generatedAt", LocalDateTime.now());

        switch (type.toLowerCase()) {
            case "user":
                report.put("data", generateUserReport(startDate, endDate));
                break;
            case "material":
                report.put("data", generateMaterialReport(startDate, endDate));
                break;
            case "copywriting":
                report.put("data", generateCopywritingReport(startDate, endDate));
                break;
            case "ai":
                report.put("data", generateAiReport(startDate, endDate));
                break;
            case "system":
                report.put("data", generateSystemReport(startDate, endDate));
                break;
            default:
                report.put("data", generateOverallReport(startDate, endDate));
        }

        return report;
    }

    /**
     * 导出统计数据
     *
     * @param type      数据类型
     * @param format    导出格式
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @return 导出文件路径
     */
    @Override
    public String exportStatisticsData(String type, String format, LocalDateTime startDate, LocalDateTime endDate) {
        log.info("导出统计数据: type={}, format={}, startDate={}, endDate={}", type, format, startDate, endDate);

        // TODO: 实现具体的导出逻辑
        String fileName = String.format("statistics_%s_%s_%d.%s",
                type,
                startDate.toLocalDate().toString(),
                System.currentTimeMillis(),
                format.toLowerCase());

        return "/exports/" + fileName;
    }

    /**
     * 获取实时统计数据
     *
     * @return 实时统计数据
     */
    @Override
    public Map<String, Object> getRealTimeStatistics() {
        log.info("获取实时统计数据");

        Map<String, Object> statistics = new HashMap<>();

        LocalDateTime now = LocalDateTime.now();
        LocalDateTime hourAgo = now.minusHours(1);

        statistics.put("currentTime", now);
        statistics.put("onlineUsers", getCurrentOnlineUsers());
        statistics.put("recentUploads", materialRepository.countByDateRange(hourAgo, now));
        statistics.put("recentGenerations", generationRecordRepository.countByDateRange(hourAgo, now));
        statistics.put("systemLoad", getCurrentSystemLoad());

        return statistics;
    }

    /**
     * 刷新统计缓存
     */
    @Override
    public void refreshStatisticsCache() {
        log.info("刷新统计缓存");

        // TODO: 实现缓存刷新逻辑
        // 这里可以清除Redis缓存或重新计算统计数据
    }

    // 私有辅助方法

    private double calculateUserRetentionRate(int days) {
        // TODO: 实现用户留存率计算逻辑
        return 0.75; // 模拟数据
    }

    private double calculateUserGrowthRate(int days) {
        // TODO: 实现用户增长率计算逻辑
        return 0.15; // 模拟数据
    }

    private long getTotalRequestsCount() {
        // TODO: 从日志或监控系统获取总请求数
        return 100000; // 模拟数据
    }

    private long getErrorRequestsCount() {
        // TODO: 从日志或监控系统获取错误请求数
        return 500; // 模拟数据
    }

    private long getSystemUptime() {
        // TODO: 获取系统运行时间
        return System.currentTimeMillis(); // 模拟数据
    }

    private int getCurrentOnlineUsers() {
        // TODO: 从会话管理器获取当前在线用户数
        return 50; // 模拟数据
    }

    private double getCurrentSystemLoad() {
        // TODO: 获取当前系统负载
        return 0.65; // 模拟数据
    }

    private Map<String, Object> generateUserReport(LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> report = new HashMap<>();
        report.put("newUsers", userRepository.countNewUsersBetween(startDate, endDate));
        report.put("activeUsers", userRepository.countActiveUsersBetween(startDate, endDate));
        return report;
    }

    private Map<String, Object> generateMaterialReport(LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> report = new HashMap<>();
        report.put("newMaterials", materialRepository.countByDateRange(startDate, endDate));
        report.put("totalViews", materialRepository.sumViewCountByDateRange(startDate, endDate));
        report.put("totalDownloads", materialRepository.sumDownloadCountByDateRange(startDate, endDate));
        return report;
    }

    private Map<String, Object> generateCopywritingReport(LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> report = new HashMap<>();
        report.put("newCopywritings", copywritingRepository.countByDateRange(startDate, endDate));
        report.put("totalUsage", copywritingRepository.sumUsageCountByDateRange(startDate, endDate));
        return report;
    }

    private Map<String, Object> generateAiReport(LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> report = new HashMap<>();
        report.put("totalGenerations", generationRecordRepository.countByDateRange(startDate, endDate));
        report.put("successfulGenerations", generationRecordRepository.countSuccessfulByDateRange(startDate, endDate));
        report.put("totalCost", generationRecordRepository.sumCostByDateRange(startDate, endDate));
        return report;
    }

    private Map<String, Object> generateSystemReport(LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> report = new HashMap<>();
        report.put("totalRequests", getTotalRequestsCount());
        report.put("errorRequests", getErrorRequestsCount());
        report.put("averageResponseTime", generationRecordRepository.getAverageResponseTimeBetween(startDate, endDate));
        return report;
    }

    private Map<String, Object> generateOverallReport(LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> report = new HashMap<>();
        report.put("userReport", generateUserReport(startDate, endDate));
        report.put("materialReport", generateMaterialReport(startDate, endDate));
        report.put("copywritingReport", generateCopywritingReport(startDate, endDate));
        report.put("aiReport", generateAiReport(startDate, endDate));
        report.put("systemReport", generateSystemReport(startDate, endDate));
        return report;
    }
}